﻿using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Web; 
using System.Web.Mvc;
using System.Reflection;
using System.ComponentModel.DataAnnotations;
using System;

namespace SRF.UI.Html
{
    public static class DictExtensions
    {
        #region DictDropDownList

        public static MvcHtmlString DictDropDownList(this HtmlHelper htmlHelper, string name, string dictCode)
        {
            return DictDropDownList(htmlHelper, name, dictCode, null /* optionLabel */, null /* htmlAttributes */);
        }

        public static MvcHtmlString DictDropDownList(this HtmlHelper htmlHelper, string name, string dictCode, object htmlAttributes)
        {
            return DictDropDownList(htmlHelper, name, dictCode, null /* optionLabel */, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        public static MvcHtmlString DictDropDownList(this HtmlHelper htmlHelper, string name, string dictCode, IDictionary<string, object> htmlAttributes)
        {
            return DictDropDownList(htmlHelper, name, dictCode, null /* optionLabel */, htmlAttributes);
        }

        public static MvcHtmlString DictDropDownList(this HtmlHelper htmlHelper, string name, string dictCode, string optionLabel)
        {
            return DictDropDownList(htmlHelper, name, dictCode, optionLabel, null /* htmlAttributes */);
        }

        public static MvcHtmlString DictDropDownList(this HtmlHelper htmlHelper, string name, string dictCode, string optionLabel, object htmlAttributes)
        {
            return DictDropDownList(htmlHelper, name, dictCode, optionLabel, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        public static MvcHtmlString DictDropDownList(this HtmlHelper htmlHelper, string name, string dictCode, string optionLabel, IDictionary<string, object> htmlAttributes)
        {
            return System.Web.Mvc.Html.SelectExtensions.DropDownList(htmlHelper, name,
                GetSelectList(SRF.Components.DataDictionary.DataDictionaryHelper.GetDictionaryItems(dictCode)), optionLabel, htmlAttributes);
        }

        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString DictDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            return DictDropDownListFor(htmlHelper, expression, "", null /* optionLabel */, null /* htmlAttributes */);
        }

        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString DictDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return DictDropDownListFor(htmlHelper, expression, "", null /* optionLabel */, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString DictDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes)
        {
            return DictDropDownListFor(htmlHelper, expression, "", null /* optionLabel */, htmlAttributes);
        }

        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString DictDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string dictCode)
        {
            return DictDropDownListFor(htmlHelper, expression, dictCode, null /* optionLabel */, null /* htmlAttributes */);
        }

        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString DictDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string dictCode, object htmlAttributes)
        {
            return DictDropDownListFor(htmlHelper, expression, dictCode, null /* optionLabel */, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString DictDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string dictCode, IDictionary<string, object> htmlAttributes)
        {
            return DictDropDownListFor(htmlHelper, expression, dictCode, null /* optionLabel */, htmlAttributes);
        }

        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString DictDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string dictCode, string optionLabel)
        {
            return DictDropDownListFor(htmlHelper, expression, dictCode, optionLabel, null /* htmlAttributes */);
        }

        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString DictDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string dictCode, string optionLabel, object htmlAttributes)
        {
            // 获取 DictAttribute 定义的字典编码
            if (string.IsNullOrEmpty(dictCode) && expression.Body.NodeType == ExpressionType.MemberAccess)
            {
                MemberExpression memberExpression = (MemberExpression)expression.Body;
                string propertyName = memberExpression.Member is PropertyInfo ? memberExpression.Member.Name : null;
                var dictAttrs = typeof(TModel).GetProperty(propertyName).GetCustomAttributes(typeof(SRF.Components.DataDictionary.DictAttribute), false);
                if (dictAttrs.Length > 0)
                {
                    SRF.Components.DataDictionary.DictAttribute dictAttr = dictAttrs[0] as SRF.Components.DataDictionary.DictAttribute;
                    dictCode = dictAttr.Code;
                }
            }
            return System.Web.Mvc.Html.SelectExtensions.DropDownListFor(htmlHelper, expression,
                GetSelectList(SRF.Components.DataDictionary.DataDictionaryHelper.GetDictionaryItems(dictCode)), optionLabel, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        #endregion

        #region DictLabel

        public static MvcHtmlString DictText(this HtmlHelper htmlHelper, string value)
        {
            string text = SRF.Components.DataDictionary.DataDictionaryHelper.GetDictionaryText(value);

            return new MvcHtmlString(text);
        }

        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString DictTextFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string dictCode = null)
        {
            // 获取 DictAttribute 定义的字典编码
            if (string.IsNullOrEmpty(dictCode) && expression.Body.NodeType == ExpressionType.MemberAccess)
            {
                MemberExpression memberExpression = (MemberExpression)expression.Body;
                string propertyName = memberExpression.Member is PropertyInfo ? memberExpression.Member.Name : null;
                var dictAttrs = typeof(TModel).GetProperty(propertyName).GetCustomAttributes(typeof(SRF.Components.DataDictionary.DictAttribute), false);
                if (dictAttrs.Length > 0)
                {
                    SRF.Components.DataDictionary.DictAttribute dictAttr = dictAttrs[0] as SRF.Components.DataDictionary.DictAttribute;
                    dictCode = dictAttr.Code;
                }
            }

            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            string text = SRF.Components.DataDictionary.DataDictionaryHelper.GetDictionaryText(metadata.Model.ToString());

            return new MvcHtmlString(text);
        }

        #endregion

        private static IEnumerable<SelectListItem> GetSelectList(IEnumerable<KeyValuePair<string, string>> dictItems)
        {
            IList<SelectListItem> items = new List<SelectListItem>();
            foreach (KeyValuePair<string, string> kv in dictItems)
            {
                items.Add(new SelectListItem()
                {
                    Text = kv.Value,
                    Value = kv.Key
                });
            }
            return items;
        }
    }
}